#[derive(Debug)]
struct Dog {
  name: String,
  weight: f32,
  height: f32,
}

impl Dog {
  fn get_name(&self /*或则使用 → &mut self*/) -> &str {
    &(self.name[..])
  }
  fn get_weight(&self) -> f32 {
    self.weight
  }
  fn get_height(&self) -> f32 {
    self.height
  }
}

//每个结构体都允许拥有多个 impl 块。
impl Dog {
  fn wang() {
    println!("wang wang wang !");
  }
  //如果直接 dog.wang() 这样调用会报错
  //↑ to be used as methods, functions must have a `self` parameter
  //  help: use associated function syntax instead: `Dog::wang`
  // 按照指示, 没有self的需要这样调用 ---> Dog::wang();
  // associated function ---> 类似于其它语言的静态方法
  //
  //https://kaisery.github.io/trpl-zh-cn/ch05-03-method-syntax.html
  //impl 块的另一个有用的功能是：允许在 impl 块中定义 不 以 self 作为参数的函数。
  //这被称为 关联函数（associated functions），因为它们与结构体相关联。
  //它们仍是函数而不是方法，因为它们并不作用于一个结构体的实例。你已经使用过 String::from 关联函数了。
  //关联函数经常被用作返回一个结构体新实例的构造函数。例如我们可以提供一个关联函数，它接受一个维度参数并且同时作为宽和高，这样可以更轻松的创建一个正方形 Rectangle 而不必指定两次同样的值：
  /*
    impl Rectangle {
    fn square(size: u32) -> Rectangle {
      Rectangle { width: size, height: size }
    }
    let sq = Rectangle::square(3);
  */


  // 而一旦这个函数的参数里包括 self, 即要用到 this, 那说明就是个实例方法
  fn wang2(&self){
    println!("wang2~~~");
  }
}

fn main() {
  let dog = Dog {
    name: String::from("feige"),
    weight: 100.0,
    height: 180.5
  };
  println!("dog: {:#?}", dog);
/*
dog: Dog {
    name: "feige",
    weight: 100.0,
    height: 180.5,
}
*/
  println!("dog.get_name ---> {}", dog.get_name()); //dog.get_name ---> feige
  println!("dog.get_height ---> {}", dog.get_height()); //dog.get_height ---> 180.5

  // dog.wang(); //to be used as methods, functions must have a `self` parameter
  Dog::wang(); //wang wang wang !
  dog.wang2(); //wang2~~~
}
